#coding: utf-8
#python不是解释型的，即也有编译的过程，编译的pyc文件，是放在虚拟机上运行的。
print("############# 一般运算 #############")

#+-*/ 没有特别的地方 ; 整数运算无溢出 浮点数运算会溢出
print(2 ** 3) #输出8 幂运算 2的3次方
print(str(10//3) + '-' + str(10%3)) #输出2-1 商与余数
print(divmod(10,3)) #输出(3,1) (商,余)

#五舍六入
print(round(1.46,1)) #1.5
print(round(1.45,1)) #1.4
print(round(10/9,3)) #1.111

print("############# 进制BUG #############")

# 自带bug 由10、2进制转换导致
print(10.0/3) #输出 3.3333333333333335
print(0.1 + 0.2) #输出 0.30000000000000004

# 引用模块解决bug
import decimal
import fractions
print(decimal.Decimal("10.0")/decimal.Decimal("3")) #输出3.333333333333333333333333333
print(decimal.Decimal("0.1") + decimal.Decimal("0.2")) #输出0.3
print(fractions.Fraction(10,3)) #输出10/3 输出有理数

print("############# math模块 #############")
import math
print(math.pi) #输出 3.141592653589793

print("############# 字符串 #############")

#转义字符没什么特别的
#原始字符串
print(r"c:\news") #输出 c:\news 所见即所得 不会换行

print("hello" + "," + "world") #输出 hello,world
print("相约" + str(2018)) #输出 相约2018
print("相约" + repr(2018)) #输出 相约2018

arrayStr = "hello world"
print("字符串长度：" + str(len(arrayStr))) #输出 字符串长度：11
#索引访问规则  [起始位置:结束位置:步长]
print(arrayStr[0] + "-" + arrayStr[0:6] + "-" + arrayStr[:6] + "-" + arrayStr[6:])
print(arrayStr[::2]) #输出 hlowrd  即设置步长
print(arrayStr.index("l")) #输出 2

arrayStrShadow = arrayStr[:] #与arrayStr完全相等
if(id(arrayStr) == id(arrayStrShadow)):
    print("arrayStr和arrayStrShadow指向同一个内址")

print("hello" in arrayStr) #True

print("-"*5) #输出 -----  将"-"重复5次

print("最大：" + max(arrayStr) + " 最小：" + min(arrayStr)) #输出 最大：w 最小： [空格]
print(ord("y")) #输出 121  字符"y"的编码值
print(str(ord("中")) + "-" + str(ord("国"))) #输出 20013-22269
print(chr(20013) + chr(22269)) #输出中国 编码转字符

#字符串格式化输出
print("%d %s"%(9527,"报道")) #输出 9527报道 最多写3个参数 此方法不建议使用
print("你好，{0}，你的余额不足{1}元。".format("yannie",10)) #输出 你好，yannie，你的余额不足10元
print("你好, {name}, 你的余额不足{balance}元".format(name="yannie",balance="10")) #输出 同上
data = {"name":"yannie","balance":"10"}
print("你好, {name}, 你的余额不足{balance}元".format(**data)) #输出 同上

print("对齐方式：\n |{0:10}| \n |{1:>15}| \n |{2:^20}|".format("左对齐-长度10","右对齐-长度15","居中对齐-长度20"))
#{<位置>:<对齐方式><0-位数不足是否补0><长度><.小数保留位数><数据类型>}
print("数字: \n |{0:<10d}| \n |{1:>10f}| \n |{2:^010.2f}|".format(1,1.0,10.12345)) #默认是右对齐 和字符是反的

#其他一些字符串方法
print("hello,world".isalpha()) #输出 False 判断是否全由字母组成
print("i like coding".split(" ")) #输出 ['i', 'like', 'coding']
print("  去掉两边空格   ".strip())
print("  去掉左边空格".lstrip())
print("去掉右边空格   ".rstrip())
print("-".join("i like coding".split(" "))) #输出 i-like-coding 连接字符串

print("############# 输入 #############")

#username = input("输入用户名:")
#print("你好," + username)

print("############# 编码 #############")

import  sys
print("当前环境编码为：" + sys.getdefaultencoding())
#因为python3支持unicode，而python2不支持，因此只有在python3中可以用以下方式查看汉字的编码
print(ord("中"))
#对一个字符串用指定方式编码解码
print("中国".encode("UTF-8")) #输出 b'\xe4\xb8\xad\xe5\x9b\xbd'
print("中国".encode("GB2312")) #输出  b'\xd6\xd0\xb9\xfa'
print(b'\xe4\xb8\xad\xe5\x9b\xbd'.decode("UTF-8","strict"))
print(b'\xd6\xd0\xb9\xfa'.decode("GB2312","strict"))

print("############# 列表 #############")

#类似字符串，大多数方法都一样

print(type([])) #输出 <class 'list'>
print(bool([])) #输出 False 判断对象Falsy或Truely
#可以存放任何东西
mylist = ['字符串', 1, ['list-1', 'list-2', 'list-3'], 'hello,world']
print(mylist)

#修改 这里与字符串不同 字符串不能修改
to_be_update_list = ['yannie','cindy']
to_be_update_list[0] = 'yanniecheung'
to_be_update_list.append("urumi")
to_be_update_list[len(to_be_update_list):] = ["zhangsan"]
print(to_be_update_list)

#访问
#2维访问
print(mylist[2][1] + "-" + mylist[3][:5]) #输出 ist-2-hello
print(['a','b','c'].index('a')) #输出 1

mylist_2 = [1,2,3,4,5,6,7,8,9,10]
print(mylist_2[::3]) #输出 [1, 4, 7, 10]  设置步长为3

#反转 字符串同理
print(mylist_2[::-1]) #输出 [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
print(list(reversed(mylist_2))) #输出 [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
print(mylist_2[::-2]) #输出 [10, 8, 6, 4, 2]

#其他一些方法 字符串同理
print(len(mylist_2))
print(mylist + mylist_2)
print(mylist_2 * 3)
print("字符串" in mylist)

#extend的参数必须是iterable的，因此不能是数字
mylist_3 = ['a','b','c']
mylist_3.extend(mylist_2)
print(mylist_3)
print(mylist_2)
#可以用以下方法判断是否可迭代 即查看对象是否含有__iter__()方法
hasattr(mylist_2,'__iter__')
hasattr("字符串",'__iter__')
hasattr(5,'__iter__') #输出 False

mylist_4 = ['a','a','b','c']
print(mylist_4.count("a"))
print(mylist_4.count("b"))
mylist_4.insert(3,"-")
print(mylist_4)
mylist_4.remove("-") #不存在或报错 可以先判断 '-' in list
mylist_4.pop(1) #弹出索引为1的元素
mylist_4.pop() #弹出最后个元素
print(mylist_4)

mylist_5 = ['a','b','c']
mylist_5_r = list(reversed(mylist_5))
print(mylist_5)
print(mylist_5_r)
mylist_5.reverse()
print(mylist_5)

mylist_6 = [9,5,2,7]

mylist_6.sort()
print(mylist_6)
mylist_6.sort(reverse=True)
print(mylist_6)

print('############# 元组 特有 比较重要 #############')

tpl_1 = 123, 'abc', [456,'def']
tpl_2 = (123, 'abc', [456,'def'])

#与list互相转换
tpl_to_list = list(tpl_1)
print(type(tpl_1))
print(type(tpl_to_list))
list_to_tpl = tuple(tpl_to_list)
print(type(tpl_to_list))
print(type(list_to_tpl))

#元组唯一与list区别，即不能修改，因此这里可以使用任何不导致其内容修改的list的方法

#什么时候用
# 因为其速度快，因此如果有一系列值，只需要遍历时，就用它
# 当做常量使用时
# 当做map的key

print("############# map #############")

my_dict = {"username":"yannie","password":123456,"site":"https://gitee.com/YannieCheung"}
my_dict["age"] = 30 #加一条entry
print(my_dict)

#利用元组构建map
tpl_for_dict = (["first","youku"],["second","aiqiyi"])
dict_by_tpl = dict(tpl_for_dict)
print(dict_by_tpl)

dict_by_fromkeys = {}.fromkeys(("third","forth"), "youtube")
print(dict_by_fromkeys)

#一些操作
#访问
print(dict_by_fromkeys["third"])
#长度
print(len(dict_by_fromkeys))
#赋值
dict_by_fromkeys["forth"] = "bilibili"
#删除
del dict_by_tpl["second"]
#存在
print("second" in dict_by_tpl)

#输出加强 web中可作为模板使用
user_info = {"username":"yannie","balance":10}
print('你好，{username}, 你的余额不足{balance}元'.format(**user_info))

#map 相关的方法
#复制一份，若用 = 则是单纯的引用地址
user_info_copy = user_info.copy()
print(id(user_info)) #输出 60241024
print(id(user_info_copy)) #输出 59611320
user_info['balance'] = 20
print(user_info_copy) # 输出 {'username': 'yannie', 'balance': 10} 保持不变

user_info["detail"] = ["vip","no9527"]
print(user_info) # 输出 {'username': 'yannie', 'balance': 20, 'detail': ['vip', 'no9527']}
user_info_copy_2 = user_info.copy()
user_info["detail"].append("20180404")
print(user_info_copy_2) # 输出 {'username': 'yannie', 'balance': 20, 'detail': ['vip', 'no9527', '20180404']}
#得出结论 这种叫做浅拷贝 两个不同dict中的这两个列表是引用同一个对象
print(id(user_info["detail"])) # 输出 60447880
print(id(user_info_copy_2["detail"])) #输出 60447880

#那么相对的有 深拷贝 方法
import copy
user_info_copy_3 = copy.deepcopy(user_info)
user_info["detail"].append("32scores")
print(user_info_copy_3["detail"]) # 输出 ['vip', 'no9527', '20180404']

#获取
print(user_info_copy_3.get("detail"))
print(user_info_copy_3.get("nothing")) # 与 dict[key]不同 没有key时不会报错
print(user_info_copy_3.setdefault("nothing","default value")) # 若有 什么都不做 直接返回 若无 设置默认值 返回

#删除单个entry
#和list不一样 参数不能为空
print(user_info_copy_3.pop("nothing")) #输出 default value  根据键弹出entry
print(user_info_copy_3) #输出 {'username': 'yannie', 'balance': 20, 'detail': ['vip', 'no9527', '20180404']} nothing 没了
#弹出不存在的key 将报错 若不想报错就提供第二个参数 作为没有key时的返回信息
print(user_info_copy_3.pop("nothing","若没有nothing,就返回这个信息")) #输出
print(user_info_copy_3)
print(user_info_copy_3.popitem()) #随机删除一个
print(user_info_copy_3)

#更新
user_info_copy_3.update([("email","123@123.com"),("age","12")])
print(user_info_copy_3) #{'username': 'yannie', 'balance': 20, 'email': '123@123.com', 'age': '12'}
user_info_copy_3.update({"address":"xxx"})
print(user_info_copy_3) #{'username': 'yannie', 'balance': 20, 'email': '123@123.com', 'age': '12', 'address': 'xxx'}

#打印键值 键 值
print(user_info_copy_3.items())
print(user_info_copy_3.keys())
print(user_info_copy_3.values())

#清空与删除
user_info_copy_3.clear()
del user_info_copy_3

print("############# SET #############")

#创建
#无序 无索引
#由于set有元素唯一的特性，因此在创建时，可以过滤重复元素
my_set_1 = set("aaaabbcccc")
my_set_2 = set(["a","a","b","c","c"])
my_set_3 = {"a","a","b","c","c"} #这种方式不能建立一个空set ,因为{}默认是个dict
#以下abc输出顺序不一定，因为无序
print(my_set_1) #输出 {'b', 'a', 'c'}
print(my_set_2) #输出 {'b', 'a', 'c'}
print(my_set_3) #输出 {'a', 'b', 'c'}

#set是不可变的，即不可以把可变的list、dict类型当成元素放入set
#my_set_4 = {[1,2],{"a":"b","c":"d"}}

#增加
my_set_1.add("d")

#合并
my_set_4 = set("efg")
my_set_1.update(my_set_4)
print(my_set_1)

#删除
print(my_set_1.pop()) #随机删除一个元素，不能指定参数
my_set_1.remove("a") #删除指定元素，元素必须存在
print(my_set_1)
my_set_1.discard("z") #删除指定元素，元素不是必须存在
my_set_1.clear() #清空
print(bool(my_set_1)) #False

f_set = frozenset("abc")
#f_set.add("d") #报错 frozenset没有add方法 不可变

#运算
print("a" in my_set_2) #True
print(my_set_2 == my_set_3) #True 两个集合元素是否一样
my_set_5 = set("ab")
print(my_set_5 < my_set_2) #True 前者是否是后者子集
print(my_set_5.issubset(my_set_2)) #同上
my_set_6 = set("opq")
print(my_set_6 | my_set_2) # ∪
print(my_set_6.union(my_set_2)) #同上

#其他还有些集合运算 略

print("############# 辅助功能 #############")

print(id(1)) #输出 1622305808  1这个对象所在内址
print(type(1)) #输出 <class 'int'>
help(id) #输出内建函数的API
print(dir(math)) #查看模块math内部结构
import keyword
print(keyword.kwlist) #查看python保留字
